<template>
	<div>
		<a-row :gutter="10" :body-style="{ 'padding-bottom': '0px' }" class="mb-2">
			<a-col :span="24">
				<a-card :bordered="false">
					<a-row>
						<a-col :span="6">
							<div class="grid-content ep-bg-purple">名称：{{ ds.datasourceName }}</div>
						</a-col>
						<a-col :span="6">
							<div class="grid-content ep-bg-purple-light">数据库类型：{{ ds.dbTypeCode }}</div>
						</a-col>
						<a-col :span="6">
							<div class="grid-content ep-bg-purple">数据库:{{ ds.db }}</div>
						</a-col>
						<a-col :span="6">
							<div class="grid-content ep-bg-purple-light">ip:{{ ds.ip }}</div>
						</a-col>
					</a-row>
				</a-card>
			</a-col>
		</a-row>

		<a-row :gutter="10">
			<a-col :span="5">
				<a-card :bordered="false">
					<div style="height: 500px; overflow-x: scroll; width: 100%">
						<DatabaseTree
							:dataSourceId="ds.id"
							:type="type"
							:schemaId="props.param?.schemaId"
							:tableName="props.param?.tableName"
							:editor="false"
							:selectChange="selectChange"
						/>
					</div>
				</a-card>
			</a-col>

			<a-col :span="19">
				<a-card :bordered="false" class="mb-2">
					<a-row>
						<a-col :span="20"></a-col>
						<a-col :span="4">
							<a-space>
								<a-button type="primary" @click="run()">运行</a-button>
								<a-button type="default" @click="explain()">执行计划</a-button>
							</a-space>
						</a-col>
					</a-row>
				</a-card>

				<a-card :bordered="false" class="mb-2">
					<div style="height: 150px; text-align: left" id="monacoEditor" ref="monacoEditor"
						 class="monaco-editor"/>
				</a-card>
				<a-card :bordered="false" class="mb-2">
					<a-tabs v-model:activeKey="activeName" class="demo-tabs">
						<a-tab-pane tab="结果集" key="resultSet" style="overflow-x: scroll">
							<h-table :data="tableData" :columns="columns" height="130px"></h-table>
						</a-tab-pane>
						<a-tab-pane tab="执行日志" key="executeLog">{{ executeLog }}</a-tab-pane>
					</a-tabs>
				</a-card>
			</a-col>
		</a-row>
	</div>
</template>

<script setup name="sqlRunner">
import * as monaco from 'monaco-editor'
import {language} from 'monaco-editor/esm/vs/basic-languages/sql/sql'
import {onMounted, onBeforeUnmount, ref, getCurrentInstance, h} from 'vue'
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
import FlinkSQLWorker from 'monaco-sql-languages/esm/languages/flink/flink.worker?worker';
import SparkSQLWorker from 'monaco-sql-languages/esm/languages/spark/spark.worker?worker';
import HiveSQLWorker from 'monaco-sql-languages/esm/languages/hive/hive.worker?worker';
import PGSQLWorker from 'monaco-sql-languages/esm/languages/pgsql/pgsql.worker?worker';
import MySQLWorker from 'monaco-sql-languages/esm/languages/mysql/mysql.worker?worker';
import TrinoSQLWorker from 'monaco-sql-languages/esm/languages/trino/trino.worker?worker';
import ImpalaSQLWorker from 'monaco-sql-languages/esm/languages/impala/impala.worker?worker';


import dataSourceApi from '@/api/datasource/dataSourceApi'
import DatabaseTree from '@/views/datasource/databaseTree.vue'
import 'monaco-sql-languages/esm/all.contributions';
import {LanguageIdEnum} from 'monaco-sql-languages';
import {vsPlusTheme} from 'monaco-sql-languages';


import {currentInfo} from '@/views/datasource/completionService.js';

const activeName = ref('resultSet')
const executeLog = ref('')
const columns = ref([])
const tableData = ref([])
self.MonacoEnvironment = {
	getWorker(workerId, label) {
		if (label === LanguageIdEnum.FLINK) {
			return new FlinkSQLWorker();
		}
		if (label === LanguageIdEnum.HIVE) {
			return new HiveSQLWorker();
		}
		if (label === LanguageIdEnum.SPARK) {
			return new SparkSQLWorker();
		}
		if (label === LanguageIdEnum.PG) {
			return new PGSQLWorker();
		}
		if (label === LanguageIdEnum.MYSQL) {
			return new MySQLWorker();
		}
		if (label === LanguageIdEnum.TRINO) {
			return new TrinoSQLWorker();
		}
		if (label === LanguageIdEnum.IMPALA) {
			return new ImpalaSQLWorker();
		}
		return new EditorWorker();
	}
}

//
// const renderHeader = ({column, $index}) => {
// 	// 新建一个 span
// 	let span = document.createElement('span');
// 	// 设置表头名称
// 	span.innerText = column.label;
// 	// 临时插入 document
// 	document.body.appendChild(span);
// 	// 重点：获取 span 最小宽度，设置当前列，注意这里加了 20，字段较多时还是有挤压，且渲染后的 div 内左右 padding 都是 10，所以 +20 。（可能还有边距/边框等值，需要根据实际情况加上）
// 	column.minWidth = span.getBoundingClientRect().width + 30;
// 	// 移除 document 中临时的 span
// 	document.body.removeChild(span);
// 	return h('span', column.label);
// };

const contextData = ref()
const selectChange = (data) => {
	contextData.value = data

	if (data.type == 'table') {
		if (props.param) {
			props.param.schemaId = data.schemaId
			props.param.tableName = data.title
		}
	}
}

// 获取 SQL 的关键字
const {keywords} = language
let editor = null


const ds = ref({
	datasourceName: '',
	dbTypeCode: '',
	db: '',
	ip: '',
	id: null
})

// 编辑器的主题设置
const theme = 'vs-dark'

const {proxy} = getCurrentInstance()


const run = async () => {
	var value = editor.getValue()
	var sb = editor.getModel().getValueInRange(editor.getSelection())
	if (sb) {
		value = sb
	}
	if (!dataSourceId.value) {
		return
	}
	let args = {}
	if (props.getRunArgs) {
		args = props.getRunArgs()
	}
	var s = await dataSourceApi.run({
		id: dataSourceId.value,
		sql: value,
		type: type.value,
		args
	})
	if (s) {
		columns.value = []
		if (s.headers) {
			for (const c of s.headers) {
				columns.value.push({
					title: c,
					dataIndex: c,
					width: 100,
					ellipsis: true,
					resizable: true,
					key: c
				})
			}
		}

		if (s.rows) {
			tableData.value = s.rows
			console.log(s.rows)
		} else {
			tableData.value = []
		}

		var str = ''
		if (s.message) {
			str += s.message + '\n'
		}
		str += '执行完成,耗时' + s.time + 'ms'
		executeLog.value = str
	}
}
const explain = async () => {
	var value = editor.getValue()
	var sb = editor.getModel().getValueInRange(editor.getSelection())
	if (sb) {
		value = sb
	}
	if (!dataSourceId.value) {
		return
	}

	value = 'explain ' + value
	let args = {}
	if (props.getRunArgs) {
		args = props.getRunArgs()
	}
	var s = await dataSourceApi.run({
		id: dataSourceId.value,
		sql: value,
		type: type.value,
		args
	})
	if (s) {
		let cb = []
		if (s.headers) {
			for (const c of s.headers) {
				cb.push({
					title: c,
					dataIndex: c,
					width: 100,
					ellipsis: true,
					resizable: true,
					key: c
				})
			}
		}
		columns.value = cb

		if (s.rows) {
			tableData.value = []
			tableData.value = s.rows
		} else {
			tableData.value = []
		}
		var str = ''
		if (s.message) {
			str += s.message + '\n'
		}
		str += '执行完成,耗时' + s.time + 'ms'
		executeLog.value = str
	}
}

const queryById = async () => {
	if (!dataSourceId.value) {
		ds.value.id = null
		return
	}
	var config = await dataSourceApi.queryById({
		id: dataSourceId.value,
		type: type.value
	})
	if (!config) {
		return
	}
	ds.value = config
}
const props = defineProps(['param', 'getRunArgs'])
const dataSourceId = ref()
const type = ref()
const monacoEditor = ref();

watch(
	() => props.param?.dataSourceId,
	(newValue, oldValue) => {
		dataSourceId.value = props.param.dataSourceId
		type.value = props.param.type

		queryById()
	}
)
watch(
	() => props.param?.sql,
	(newValue, oldValue) => {
		if (!editor) {
			return
		}
		const c = editor.getValue()
		if (c == props.param?.sql) {
			return
		}
		editor.setValue(props.param?.sql)
	}
)
// 组件挂载后创建编辑器实例
onMounted(async () => {
	if (props.param?.dataSourceId) {
		dataSourceId.value = props.param?.dataSourceId
		type.value = props.param?.type
	} else {
		dataSourceId.value = proxy.$route.query.id
		type.value = proxy.$route.query.type
	}
	//查询数据库详情
	await queryById()
	currentInfo.id = dataSourceId.value
	editor = monaco.editor.create(monacoEditor.value, {
		value: props.param?.sql ? props.param?.sql : 'select * from dual',
		language: LanguageIdEnum.MYSQL,
		readOnly: false,
		automaticLayout: true,
		colorDecorators: true, // 颜色装饰器
		theme: theme,
		minimap: {
			enabled: false
		},
		tabSize: 2,
		fontSize: 16
	})
	// 监听值变化
	editor.onDidChangeModelContent((event) => {
		const value = editor.getModel().getValue()
		console.log('值已变化:', value)
		// 在这里处理值变化后的逻辑
		if (props.param) {
			props.param.sql = value
		}
	})
	// const model = editor.getModel();
	// 导入主题数据并定义主题, 你可以自定义主题名称, 例如 sql-dark
	// editor.defineTheme('sql-dark', vsPlusTheme.darkThemeData);
	// editor.defineTheme('sql-light', vsPlusTheme.lightThemeData);
	// editor.defineTheme('sql-hc', vsPlusTheme.hcBlackThemeData);
	// monaco.editor.setModelLanguage(model, LanguageIdEnum.MYSQL);
// 指定你已定义的主题
// 	editor.create(null, {
// 		theme: 'sql-dark',
// 		language: 'mysql'
// 	});


})
// 组件卸载前销毁编辑器实例
onBeforeUnmount(() => {
	if (editor) {
		editor.dispose()
	}
})

/**
 * @description: 获取编辑器中填写的值
 */
function getValue() {
	return editor.getValue()
}

</script>

<style scoped></style>
